開始專案前需要先對 Flask 設定一下,讓它能夠開發的更順手(又是一段超短的開頭)。
剛剛在啟動 server 時使用到了 set
這個指令,set
其實是設定環境變數的指令,flask run
這行是使用了 flask-cli,讓 flask 自動去抓環境變數來設定並執行。不過如果現在有一堆東西要設定,一行一行慢慢寫入也太花時間,而且有時候不小心忘記設定過了什麼又要在茫茫大海中尋找,非常花時間。所以現在就要來講一下如何設定並且開始一個 flask 時有什麼要設定的。
flask 中可設定的值大概有這些 Builtin Configuration Value
首先,讓 flask 運行起來的方式有兩種,透過 flask-cli 或透過 python 來啟動。
先來說透過 flask-cli 啟動要如何設定:
flask-cli 可以抓環境變數來載入設定後執行,但是一行一行寫入不方便管理,那怎麼辦呢?
你可以透過 .env
檔或是 .flaskenv
檔(這兩個檔案的寫法都跟 Day 09 的 .env
檔一樣,啊記得放在專案根目錄)來統一管理設定,並且 flask-cli 會自動將 這兩個檔案載入到設定後才執行。
而 flask-cli 下指令的時候也可以加上參數。那這三個同時下不同指令的時候會發生什麼事呢(正常不會這樣做,我只是舉例而已)?
由於載入的順序大概是這樣 .flaskenv
=> .env
=> CLI-settings(J個是尛?flask run
這個東西,flask run --help
就可以看到怎麼使用了。再說一次,用虛擬環境的要進入虛擬環境喔),所以在後面載入的 .env
會覆蓋掉 .flaskenv
的值;更後面的 CLI-settings 又會覆蓋掉 .env
的值,大概就這樣。
.env
、.flaskenv
這兩個檔案較適用於不適合公開的設定,例如之後會講到的 SECRET_KEY
,那麼透過 python 啟動呢?
python 啟動其實就只是 python app.py
這樣而已。要執行前必須把剛剛註解的那兩行加進來,不然不會執行。
那這樣做有什麼差别呢?
這個方式可以用很多其他的方式來載入設定後再執行(不過這邊的方法都在 flask-cli 啟動時都是在執行後才會載入,這樣就沒有意義了),甚至做到只改一行就改變所有設定;不過 .env
跟 .flaskenv
就不行了(雖然 .env
可以另外透過 python-dotnev 這個模組的 load_dotenv()
這個方式額外載入)。
到底又有什麼方式可以載入設定呢?先說比較簡單的:
這應該是最簡單的,因為 Flask 的 config 其實就是一個 dict (字典,Day 03 有講到),要改寫這個 dict 就直接抓它的 key 改 value 就行了。像這樣:
from flask import Flask
app = Flask(__name__)
app.config["ENV"] = "development"
app.config["DEBUG"] = True
@ app.route("/")
def index():
return "Hello World"
if __name__ == "__main__":
app.run()
再把它 run 起來
# 再提醒一次,有用虛擬環境的要進去虛擬環境
$ pipenv shell
$ python app.py
應該可以看到 Environment 變成 development 以及 Debug 變成 on 了!
這個方式跟第一個方式其實差不多,都是基於 dict 去操作的,但是不用一個一個改,只要寫好一次 update 就可以了。大概像這樣:
from flask import Flask
CONFIGS = {
"ENV": "development",
"DEBUG": True
}
app = Flask(__name__)
app.config.update(CONFIGS)
@ app.route("/")
def index():
return "Hello World"
if __name__ == "__main__":
app.run()
# 進入虛擬環境
$ pipenv shell
$ python app.py
因為我都讓它們做同樣事情,結果不會不一樣(有不一樣就是你弄錯了),所以我就懶得放塗了。
第三個方式跟第二個差不多,不過不再基於 dict 去操作,使用的是 flask 提供的方式。像這樣:
from flask import Flask
CONFIGS = {
"ENV": "development",
"DEBUG": True
}
app = Flask(__name__)
app.config.from_mapping(CONFIGS)
@ app.route("/")
def index():
return "Hello World"
if __name__ == "__main__":
app.run()
# 進入虛擬環境
$ pipenv shell
$ python app.py
對,結果應該又是一樣的。
這個方式開始就有點不同了,是引入一個檔案(不需要 import,直接輸入檔名),需要新增一個檔案。結構長這樣:
ithome/
├── app.py
├── configs.py
├── Pipfile
└── Pipfile.lock
configs.py
ENV = 'development'
DEBUG = True
app.py
from flask import Flask
app = Flask(__name__)
app.config.from_pyfile('configs.py')
@ app.route("/")
def index():
return "Hello World"
if __name__ == "__main__":
app.run()
# 進入虛擬環境
$ pipenv shell
$ python app.py
對啦,結果又双是一樣的。
這個方式跟前一個差不多,但是需要新增環境變數,然後從環境變數中抓到該去哪裡找設定檔。像這樣:
ithome/
├── app.py
├── configs.py
├── Pipfile
└── Pipfile.lock
configs.py
ENV = 'development'
DEBUG = True
app.py
from flask import Flask
app = Flask(__name__)
app.config.from_envvar('FLASK_SETTINGS')
@ app.route("/")
def index():
return "Hello World"
if __name__ == "__main__":
app.run()
# 進入虛擬環境
$ pipenv shell
# 設定環境變數
$ set FLASK_SETTINGS=./configs.py
# 執行
$ python app.py
對啦,結果又双叒是一樣的。
這個方式是我比較喜歡的,因為可以同時存放多種設定,例如開發環境設定、部署環境設定等,不用有一堆設定檔,也不需要使用到環境變數,也支援多種方式。像這樣:
ithome/
├── app.py
├── configs.py
├── Pipfile
└── Pipfile.lock
導入後套用設定
configs.py
ENV = 'development'
DEBUG = True
app.py
from flask import Flask
import configs as CONFIGS
app = Flask(__name__)
app.config.from_object(CONFIGS)
@ app.route("/")
def index():
return "Hello World"
if __name__ == "__main__":
app.run()
# 進入虛擬環境
$ pipenv shell
$ python app.py
直接呼叫模組名稱
configs.py
ENV = 'development'
DEBUG = True
app.py
from flask import Flask
app = Flask(__name__)
app.config.from_object("configs")
@ app.route("/")
def index():
return "Hello World"
if __name__ == "__main__":
app.run()
# 進入虛擬環境
$ pipenv shell
$ python app.py
物件化多設定檔
configs.py
class Config:
TESTING = False
class ProductionConfig(Config):
FLASK_ENV = 'production'
DEBUG = False
class DevelopmentConfig(Config):
ENV = 'development'
DEBUG = True
class TestingConfig(Config):
TESTING = True
app.py
from flask import Flask
import configs
app = Flask(__name__)
app.config.from_object(configs.DevelopmentConfig)
@ app.route("/")
def index():
return "Hello World"
if __name__ == "__main__":
app.run()
# 進入虛擬環境
$ pipenv shell
$ python app.py
對啦,結果又双叒叕是一樣的。
最後,app.run()
也是可以加參數的,參考 run()
那麼就大概這樣,本來想說設定只有一點點的,可是沒想到也這麼多。
大家掰~掰~